﻿
#define FMT_HEADER_ONLY
#define FMT_UNICODE 0
#include <fmt/core.h>
#include <fmt/ranges.h>

#include "nonstd/jthread.hpp"

#include "plf_queue.h"
using namespace plf;

#include <windows.h>

#include "BlockingCollection.h"
using namespace code_machina;

BlockingQueue<std::string> cmds;

int main()
{
    std::mutex              q_mtx;
    plf::queue<std::string> q;

    const int N = 100000;

    // Production stage
    nonstd::jthread th_production_q    = nonstd::jthread([&]() {
        for (int j = 0; j < N; j++)
        {
            {
                std::lock_guard<std::mutex> guard(q_mtx);
                q.emplace(fmt::format("{}", j));
            }
        }
    });
    nonstd::jthread th_production_cmds = nonstd::jthread([&]() {
        for (int j = 0; j < N; j++)
        {
            cmds.emplace(fmt::format("{}", j));
        }
    });
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    nonstd::jthread th_consumer_q = nonstd::jthread([&]() {
        do
        {
            std::string item;

            std::lock_guard<std::mutex> guard(q_mtx);
            if (!q.empty())
            {
                fmt::println("plf - {}", q.front());
                q.pop();
            }
            else
            {
                break;
            }
        } while (true);
    });

    nonstd::jthread th_consumer_cmds = nonstd::jthread([&]() {
        do
        {
            std::string item = "000";
            cmds.take(item);
            fmt::println("code_machina - {}", item);
        } while (!cmds.is_deactivated());
    });
}